package net.sureon.web.admin;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sureon.app.AppContext;
import net.sureon.biz.CompanyMgr;
import net.sureon.biz.GroupBO;
import net.sureon.biz.GroupMgr;
import net.sureon.biz.UserBO;
import net.sureon.biz.UserMgr;
import net.sureon.common.exception.SureonException;
import net.sureon.common.security.Role;
import net.sureon.dao.Group;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.validation.BindException;
import org.springframework.validation.Errors;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import org.springframework.web.servlet.mvc.SimpleFormController;

@SuppressWarnings("unchecked")
public class ManageGroup extends SimpleFormController implements Controller {
	private static Log logger = LogFactory.getLog(ManageGroup.class);
	private UserMgr userMgr;
	private GroupMgr groupMgr;
	private CompanyMgr companyMgr;

	/**
	 * @return the userMgr
	 */
	public UserMgr getUserMgr() {
		return userMgr;
	}

	/**
	 * @param userMgr
	 *            the userMgr to set
	 */
	public void setUserMgr(UserMgr userMgr) {
		this.userMgr = userMgr;
	}

	/**
	 * @return the groupMgr
	 */
	public GroupMgr getGroupMgr() {
		return groupMgr;
	}

	/**
	 * @param groupMgr
	 *            the groupMgr to set
	 */
	public void setGroupMgr(GroupMgr groupMgr) {
		this.groupMgr = groupMgr;
	}

	/**
	 * @return the companyMgr
	 */
	public CompanyMgr getCompanyMgr() {
		return companyMgr;
	}

	/**
	 * @param companyMgr
	 *            the companyMgr to set
	 */
	public void setCompanyMgr(CompanyMgr companyMgr) {
		this.companyMgr = companyMgr;
	}

	private static final String ATTRI_GROUPS = "groups";
	private static final String ACTION = "action";
	private static final String ID = "id";
	private static final String ATTRI_GROUPFORM = "groupForm";
	private static final String ALREADY_GROUP_MANAGER = "alreadyGroupManager";

	protected Map referenceData(HttpServletRequest request, Object command,
			Errors errors) throws Exception {
		Map result = new HashMap();
		String action = request.getParameter(ACTION);
		String id = request.getParameter(ID);
		if (action != null && id != null) {
			processStandaloneAction(command, action, id);
		}
		List<GroupDisplay> list = buildGroupDropdownDisplay(AppContext
				.getCompanyID());
		result.put(ATTRI_GROUPS, list);
		GroupForm form = (GroupForm) command;
		form.setGroupManagerList(buildGroupManagerDropdownDisplay(AppContext
				.getCompanyID(), form.getGroupID()));
		form.setGroupList(buildGroupDropdownDisplay(AppContext.getCompanyID()));
		result.put(ATTRI_GROUPFORM, command);
		return result;
	}

	// 判断是否允许删除(该组内没有任何成员)
	private void processStandaloneAction(Object command, String action,
			String id) throws SureonException {
		long groupID = Long.parseLong(id);
		GroupBO group = groupMgr.getGroup(AppContext.getCompanyID(), groupID);

		if ("edit".equals(action)) {
			// 表示编辑
			GroupForm form = (GroupForm) command;
			form.setGroupID(group.getGroupID());
			form.setGroupName(group.getGroupVO().getGroupName());
			form.setParentGroup(group.getGroupVO().getParentGroup());
			form.setGroupManagerList(buildGroupManagerDropdownDisplay(
					AppContext.getCompanyID(), groupID));

			form.setGroupManager(group.getGroupVO().getGroupManager());
		} else if ("delete".equals(action)) {
			// 判断该组内是否有成员，若没有允许删除
			groupMgr.deleteNullGroup(AppContext.getCompanyID(), groupID);

		}
	}

	protected ModelAndView onSubmit(HttpServletRequest request,
			HttpServletResponse response, Object command, BindException errors)
			throws Exception {
		GroupForm groupForm = (GroupForm) command;
		if(groupForm.getGroupManager() == 0 || !isManagerOfOtherGroup(groupForm)) {
			if (groupForm.getGroupID() > 0) {
				GroupBO groupBO = groupMgr.getGroup(AppContext.getCompanyID(),
						groupForm.getGroupID());
	
				updateGroup(groupBO, groupForm);
			} else {
				createGroup(groupForm);
			}
		}else{
			request.setAttribute(ALREADY_GROUP_MANAGER, "该经理已经是其他团队的经理");
		}
		groupForm.reset();
		ModelAndView view = new ModelAndView(this.getSuccessView());
		Map result = new HashMap();
		List<GroupDisplay> list = buildGroupDropdownDisplay(AppContext
				.getCompanyID());
		result.put(ATTRI_GROUPS, list);
		// groupForm.setGroupManagerList(buildGroupDropdownDisplay(AppContext
		// .getCompanyID()));
		groupForm.setGroupManagerList(buildGroupManagerDropdownDisplay(
				AppContext.getCompanyID(), groupForm.getGroupID()));
		groupForm.setGroupList(buildGroupDropdownDisplay(AppContext
				.getCompanyID()));
		result.put(ATTRI_GROUPFORM, groupForm);
		view.addAllObjects(result);
		return view;
	}

	// 判断组是否重名，更新或添加
	private boolean isGroupNameExists(long companyID, String groupName)
			throws SureonException {
		List<GroupBO> groups = groupMgr.getGroupByName(companyID, groupName);
		return groups.size() > 0;
	}
	
	private boolean isManagerOfOtherGroup(GroupForm groupForm) throws SureonException {
		long managedGroupID = groupMgr.getManagedGroup(AppContext.getCompanyID(), groupForm.getGroupManager());
		return (managedGroupID > 0 && groupForm.getGroupID() != managedGroupID);
	}

	private void updateGroup(GroupBO groupBO, GroupForm groupForm)
			throws SureonException {
		String groupName = groupForm.getGroupName();
		if (groupName == null || "".equals(groupName)) {
			logger
					.error("update group failure, may be the group name is null or the group name is exists in this company!");
			return;
		} else {
			Group vo = groupBO.getGroupVO();
			UserBO user = null;
			// 判断该组manager是不是已经是其他组的manager，如果是，则不允许更新
//			if(isManager(groupForm)) {
//				
//			} else {
				if (isGroupNameExists(AppContext.getCompanyID(), groupName)) {
					// 如果该组名存在,判断团队名称有没有改变，若改变，不允许修改，若不改变，允许修改团队经理
					if (groupBO.getGroupVO().getGroupName().equals(
							groupForm.getGroupName())) {
						vo.setParentGroup(groupForm.getParentGroup());
						vo.setGroupManager(groupForm.getGroupManager());
					}
				} else {
					// 不存在
					vo.setGroupManager(groupForm.getGroupManager());
					vo.setGroupName(groupName);
					vo.setParentGroup(groupForm.getParentGroup());
				}
				groupMgr.updateGroup(groupBO);
				UserBO groupManagerBO = userMgr.getUser(AppContext.getCompanyID(),
						groupForm.getGroupManager());
	
				if (user == null || vo.getGroupID() != user.getGroupID()) {
					groupManagerBO.getUserVO().setRole(Role.ROLE_NAME_GROUPADMIN);
					groupManagerBO.getUserVO().setGroupID(groupBO.getGroupID());
					userMgr.updateUser(groupManagerBO);
				}
//			}
		}
	}

	private void createGroup(GroupForm groupForm) throws SureonException {
		Group vo = new Group();
//			if(isManager(groupForm)) {
//				///////////////////
//				System.out.println("create group , the user is other group manager");
//			} else {
				
				vo.setCompanyID(AppContext.getCompanyID());
				String groupName = groupForm.getGroupName();
				if (groupName == null || "".equals(groupName)
						|| isGroupNameExists(AppContext.getCompanyID(), groupName)) {
					logger
							.error("create group failure, may be the group name is null or the group name is exists in this company!");
					return;
				} else {
					vo.setGroupName(groupName);
					vo.setGroupManager(groupForm.getGroupManager());
					vo.setParentGroup(groupForm.getParentGroup());
					vo.setGroupType("Team");
				GroupBO group = new GroupBO(vo);
				long groupID = groupMgr.insertGroup(group);
				if (groupForm.getGroupManager() > 0) {
					// groupManager不為0，更新該成員為組管理員
					UserBO groupManagerBO = userMgr.getUser(AppContext
							.getCompanyID(), groupForm.getGroupManager());
					groupManagerBO.getUserVO().setRole(Role.ROLE_NAME_GROUPADMIN);
					groupManagerBO.getUserVO().setGroupID(groupID);
					userMgr.updateUser(groupManagerBO);
				}
//			}
		}
	}

	// 列出当前组的所有成员供选择
	// private List<GroupManagerDropDownDisplay>
	// buildGroupManagerDropdownDisplay(
	// long companyID, long groupID) throws SureonException {
	// List<GroupManagerDropDownDisplay> list = new
	// ArrayList<GroupManagerDropDownDisplay>();
	// // GroupBO topGroup = groupMgr.getCompanyTopGroup(companyID);
	// // userMgr.getUserByCompanyID(companyID, skipResults, maxResults)
	// List<UserBO> userBOs = userMgr.getUserByCompanyID(companyID, 1, 20);
	//
	// for (UserBO userBO : userBOs) {
	// list.add(new GroupManagerDropDownDisplay(userBO.getUserID(), userBO
	// .getUserVO().getRealName()));
	// }
	// return list;
	// }

	private boolean isNullGroup(long companyID, long groupID)
			throws SureonException {
		boolean flag = false;
		// 该组内的用户
		List<UserBO> userBOs = userMgr.getUserByGroupID(companyID, groupID);
		GroupBO groupBO = groupMgr.getGroup(companyID, groupID);
		if (userBOs == null || userBOs.size() == 0) {
			// 判断该组还有没有下属组
			if(groupBO.getChildGroups().size() == 0) {
				flag = true;
			}
		}
		return flag;
	}

	// 取得一個組當中有多人成員
	private int getGroupMemberNum(long companyID, long groupID)
			throws SureonException {
		int num = 0;
		List<UserBO> list = userMgr.getUserByGroupID(companyID, groupID);
		num = list.size();
		return num;
	}

	private List buildGroupDropdownDisplay(long companyID)
			throws SureonException {
		List<GroupDisplay> list = new ArrayList<GroupDisplay>();
		GroupBO topGroup = groupMgr.getCompanyTopGroup(companyID);
		recusiveGenerateGroupList(topGroup, list, 0);
		return list;
	}

	private void recusiveGenerateGroupList(GroupBO group,
			List<GroupDisplay> addTo, int level) throws SureonException {

		boolean isNullGroup = isNullGroup(AppContext.getCompanyID(), group
				.getGroupID());
		long groupManager = group.getGroupVO().getGroupManager();
		UserBO user = null;
		String groupManagerName = "";
		if (groupManager > 0) {
			user = userMgr.getUser(AppContext.getCompanyID(), groupManager);
			groupManagerName = user.getUserVO().getRealName();
		}

		long parentGroup = group.getGroupVO().getParentGroup();
		String parentGroupName = "";
		if (parentGroup > 0) {
			parentGroupName = groupMgr.getGroup(AppContext.getCompanyID(),
					parentGroup).getGroupVO().getGroupName();

		}
		int groupMemberNum = getGroupMemberNum(AppContext.getCompanyID(), group
				.getGroupID());

		GroupDisplay display = new GroupDisplay(group, parentGroupName,
				groupManagerName, groupMemberNum, isNullGroup);
		display.setRecusiveGroupName(strPrefix(level, group.getGroupVO()
				.getGroupName()));
		addTo.add(display);

		for (GroupBO subGroup : group.getChildGroups()) {
			recusiveGenerateGroupList(subGroup, addTo, level + 1);
		}
	}

	private static final String prefix = "-----";
	private static final String initial = "|---";

	private String strPrefix(int level, String groupName) {
		StringBuffer buff = new StringBuffer(initial);
		for (int i = 0; i < level; i++) {
			buff.append(prefix);
		}
		buff.append(groupName);
		return buff.toString();
	}

	public static class GroupDisplay {
		private GroupBO groupBO;
		private String parentGroupName;
		private String recusiveGroupName;
		private boolean nullGroup;
		private String groupManagerName;
		private long groupMemberNum;

		private GroupDisplay(GroupBO groupBO, String parentGroupName,
				String groupManagerName, int groupMemberNum, boolean nullGroup) {
			this.groupBO = groupBO;
			this.nullGroup = nullGroup;
			this.parentGroupName = parentGroupName;
			this.groupManagerName = groupManagerName;
			this.groupMemberNum = groupMemberNum;
		}

		/**
		 * @return the groupBO
		 */
		public GroupBO getGroupBO() {
			return groupBO;
		}

		/**
		 * @return the parentGroupName
		 */
		public String getParentGroupName() {
			return parentGroupName;
		}

		/**
		 * @return the recusiveGroupName
		 */
		public String getRecusiveGroupName() {
			return recusiveGroupName;
		}

		/**
		 * @param recusiveGroupName
		 *            the recusiveGroupName to set
		 */
		public void setRecusiveGroupName(String recusiveGroupName) {
			this.recusiveGroupName = recusiveGroupName;
		}

		/**
		 * @return the nullGroup
		 */
		public boolean isNullGroup() {
			return nullGroup;
		}

		/**
		 * @return the groupManagerName
		 */
		public String getGroupManagerName() {
			return groupManagerName;
		}

		/**
		 * @return the groupMemberNum
		 */
		public long getGroupMemberNum() {
			return groupMemberNum;
		}
	}

	private static class GroupManagerDropDownDisplay {
		private long groupManager;
		private String groupManagerName;

		private GroupManagerDropDownDisplay(long groupManager,
				String groupManagerName) {
			this.groupManager = groupManager;
			this.groupManagerName = groupManagerName;
		}

		public long getGroupManager() {
			return groupManager;
		}

		public void setGroupManager(long groupManager) {
			this.groupManager = groupManager;
		}

		public String getGroupManagerName() {
			return groupManagerName;
		}

		public void setGroupManagerName(String groupManagerName) {
			this.groupManagerName = groupManagerName;
		}
	}

	private List<GroupManagerDropDownDisplay> buildGroupManagerDropdownDisplay(
			long companyID, long groupId) throws SureonException {
		List<GroupManagerDropDownDisplay> list = new ArrayList<GroupManagerDropDownDisplay>();
		List<UserBO> userBOs = null;
		userBOs = userMgr.getUserByCompanyID(companyID, 0, 1000);
		for (UserBO user : userBOs) {
			list.add(new GroupManagerDropDownDisplay(user.getUserID(), user
					.getUserVO().getRealName()));
		}
		return list;
	}
}